package com.weizhu.swufer.core.filter;

import com.weizhu.swufer.constant.SwuferConstant;
import com.weizhu.swufer.core.annotation.SwuferFilter;
import com.weizhu.swufer.core.annotation.SwuferLimit;
import com.weizhu.swufer.core.entity.InvokeParam;
import com.weizhu.swufer.core.entity.RpcBaseInfo;
import com.weizhu.swufer.core.rpc.RpcEngine;
import com.weizhu.swufer.core.rpc.RpcLimitManager;
import com.weizhu.swufer.core.rpc.RpcRequest;
import com.weizhu.swufer.core.util.ClassUtil;

import java.lang.reflect.Method;

@SwuferFilter(type = {SwuferConstant.FILTER_TYPE_PROVIDER},order = -1)
public class LimitFilter implements Filter{
    @Override
    public Object doFilter(InvokeParam invokeParam, FilterChain filterChain) throws Exception {
        RpcRequest rpcRequest = invokeParam.getRpcRequest();
        String interfaceName = rpcRequest.getInterfaceName();
        String methodName = rpcRequest.getMethodName();
        Object[] args = rpcRequest.getArgs();
        Class<?>[] argTypes = rpcRequest.getArgTypes();
        if (argTypes == null){
            argTypes = ClassUtil.getParamsType(args);
        }
        RpcBaseInfo rpcBaseInfo = RpcEngine.getInstance().getLocalServiceMap().get(interfaceName);
        Object bean = rpcBaseInfo.getTarget();
        int qps = rpcBaseInfo.getQps();
        Method method = bean.getClass().getMethod(methodName,argTypes);
        SwuferLimit anno = method.getAnnotation(SwuferLimit.class);
        if (anno != null){
            qps = anno.qps();
        }
        RpcLimitManager.tryAcquire(rpcRequest,qps);
        return filterChain.doFilter(invokeParam);

    }
}
